/**
 * Create an in-browser tool for Producers 
 * - to check out/in files for tickets assigned to them
 * - to generate commonly used command "svn ci", "trig", "trig --final"
 * The tool is the front-end component as opposed to CMO App admin tool.
 * Communication between addon script and content script:
 * - checkin/out data package: used as either request and response payload
 *   + ticket: string - ServiceNow Change Request ID
 *   + files: array of string - Full file path (e.g. /home/webuser/site/templates/goodhousekeeping/_homepage.tmpl)
 *            or relative file path (e.g. templates/goodhousekeeping/_homepage.tmpl)
 * - syncData
 *   + ticket: string - ServiceNow Change Request ID
 *   + url: Redmine ussue URL
 */

/**@ tab Tab  */
// PREFERENCES
var serverHost = require("sdk/simple-prefs").prefs.cmoServerHost;
var serverPort = 8080;
var targetUrlPrefixes = require("sdk/simple-prefs").prefs.targetUrlPrefixes.split('|');
var redmineUrlPrefix = require("sdk/simple-prefs").prefs.redmineUrlPrefix;
// COMPONENTS
var data = require("sdk/self").data;
var tabs = require('sdk/tabs');
var cm = require('sdk/context-menu');
var request = require('sdk/request');
var clipboard = require('sdk/clipboard');
// ADD ON VARIABLES
var rgxTicket = /CHG\d{7}/;
var mnuCmoTools = null;

tabs.on('ready',function(tab){
	// Restrict this addon to certain URLs as defined by targetUrlPrefixes
	var url = tab.url;
	for(var i=0;i<targetUrlPrefixes.length;i++) {
		if (url.indexOf(targetUrlPrefixes[i])==0) { // startsWith		
			tab.attach({
				contentScript: 'self.postMessage(document.body.innerHTML);',
			    onMessage: function (html) {
			    	// Extract the ticketIDs from message
			    	var matches = rgxTicket.exec(html);
			    	if (matches == null || matches.length == 0) {
			    		console.log('No ticket is found in the HTML');
			    		return;
			    	}
			    	if (matches.length > 0) {
			    		updateChangeRequest(tab, matches[0]);
			    		generateContextMenu(tab, matches[0]);
			    	}
			    }
			});
			
			break;
		}
	}
});

function generateContextMenu(tab, ticketID) {
	if (mnuCmoTools != null) mnuCmoTools.destroy();
	
	mnuCmoTools = cm.Menu({
		label:'CMO Tools',
		context:cm.SelectionContext(),
		items:[cm.Item({
			label:'Check out',
			contentScript:'self.on("click", function(){' + 
				'var selection = window.getSelection().toString();' +
				'console.log(selection);' +
				'if (selection.length == 0) { ' + 
				'	var selectedElement = document.activeElement;' +
				'	selection = selectedElement.value.substring(selectedElement.selectionStart, selectedElement.selectionEnd);' +
				'}' +
				'if (selection.length == 0) { ' +
				'	console.log("No text is selected. Can this even happen??? Because context is SelectionContext!");' +
				'	return;' +
				'}' +
				'self.postMessage(selection);' +
				'})',
			data:ticketID,
			onMessage: function(selection) {
				console.log("Checking out multiple files from context menu...");
				console.log('Selection: ' + selection);
				var files = selection.split(/\r\n|\r|\n|\s/);
				// Validate file names				
					
				var checkoutData = {
						ticket:this.data,
						files:files
				};
				
				tab.worker.port.emit('file.checkout.started');
				checkoutFiles(checkoutData, function(updatedCheckoutData) {
					tab.worker.port.emit('file.checkout.complete', updatedCheckoutData);
					console.log("Checking out multiple files from context menu completed");
				});
			}
		})]
	});	
}

function updateChangeRequest(tab, ticketID) {
	var url = 'http://' + serverHost + ':' + serverPort + '/api/changerequests/' + ticketID + '/files.json';
	request.Request({
		  url: url,
		  onComplete: function (response) {
				var checkoutData = response.json;
				var registered = checkoutData != null;
				// In case ticket has not been registered with CMO
				if (checkoutData == null) {
					console.log('Ticket has not been registered with CMO');
					checkoutData = {
							id:ticketID,
							files:[]
					};
				}
				
				var ticketId = checkoutData.id;
				// Get the list of related files here
				var files = checkoutData.files;
				// Generate the checkout panel
				// Only Redmine should have the sync button 
				var activeTools = (tab.url.indexOf(redmineUrlPrefix)==0)?['sync','svn-ci','trig']:['svn-ci','trig'];
				var table = createTicketCheckoutTable(ticketId, files, activeTools);
				
				console.log(files);
				// Modify the DOM in content
				
				var worker = tab.attach({
					contentScriptFile:[	data.url('jquery-1.9.1.min.js'),
					                   	data.url('checkouts-panel.js')],
					contentScript: 	'jQuery(".subject:first, .vsplit:first").append("' + table + '");'
							//	+ (!registered)?'jQuery("#cmotool-checkouts-panel div.cmotool-message").html("Please sync ticket with CMO Server");':''
				});
				
				tab.worker = worker;
				
				worker.port.on('file.checkin', function(checkinData){
					console.log('Checking in files...');
					worker.port.emit('file.checkin.started');
					checkinFiles(checkinData, function(updatedCheckoutData) {
						worker.port.emit('file.checkin.complete', updatedCheckoutData);
						console.log('Checking in files complete');
					});
				});
				
				worker.port.on('file.checkout', function(checkoutData){
					console.log('Checking out file...');
					worker.port.emit('file.checkout.started');
					checkoutFiles(checkoutData,function(updatedCheckoutData) {
						worker.port.emit('file.checkout.complete', updatedCheckoutData);
						console.log('Checking out file complete');
					});
				});
				
				worker.port.on('ticket.sync', function(syncData) {
					console.log('Synchronizing ticket...');
					worker.port.emit('ticket.sync.started');
					syncTicket(syncData, function(updatedCheckoutData){
						worker.port.emit('ticket.sync.complete', updatedCheckoutData);
						console.log('Synchronizing ticket complete');
					});
				});
				
				worker.port.on('clipboard.copy', function(data){
					clipboard.set(data);
				});
		  }
	}).get();	
}

function createTicketCheckoutTable(ticketId, files, tools) {
	var activeTools = tools || ['sync','svn-ci','trig']; // default config for the toolbar 
	var table = "<style>" +
		"div#cmotool-checkouts-panel {position:relative;border: 1px solid #CCCCCC;margin-bottom: 10px;padding: 5px;}"+
		".cmotool-sync,.cmotool-trig,.cmotool-svn-ci{display:inline-block;width:16px;height:16px;margin-right:3px;background-repeat:none;cursor:pointer}" +
		".cmotool-sync{background-image:url(" + data.url('sync.png') + ")}" +
		".cmotool-trig{background-image:url(" + data.url('trig-beta.png') + ")}" +
		".cmotool-svn-ci{background-image:url(" + data.url('subversion.png') + ")}" +
		".cmotool-loading{position:absolute;display:none;right:0;top:5px;width:48px;height:16px;background:url(" + data.url('loading.gif') + ") no-repeat}" +
		".cmotool-message{margin:10px 0}" +
		".cmotool-checkouts-list{padding-left: 0}" +		
		".cmotool-checkouts-list > li{list-style-position: inside}" +
		".cmotool-checkin{margin-left: 20px;float: right;cursor:pointer}" + 
		".cmotool-checkout{cursor:pointer}" +		
		"</style>";
	table += "<div id='cmotool-checkouts-panel' data-ticket-id='" + ticketId + "'>";
	table += "	<h3>CMO Tool - Checkout Panel</h3>";
	// Config the toolbar
	if (activeTools.indexOf('sync')!=-1)
		table += "<span class='cmotool-sync'></span>";
	if (activeTools.indexOf('svn-ci')!=-1)
		table += "<span class='cmotool-svn-ci'></span>";
	if (activeTools.indexOf('trig')!=-1)
		table += "<span class='cmotool-trig'></span>";
	
	table += "<span class='cmotool-loading'></span>";
	table += "	<div class='cmotool-message'></div>";
	table += "	<ol class='cmotool-checkouts-list'>";
	for(var i=0;i<files.length;i++)
		table += "	<li><span>" + normalizeFilename(files[i]) + "</span><a class='cmotool-checkin' data-filename=" + files[i] + ">Check in</a></li>";
	table += "	</ol>"; // cmotool-checkouts-list
	table += "	<div class='cmotool-new-checkout'>";
	table += "		<span>File:</span> <input id='cmotool-new-checkout-filename' size='60' />";
	table += "		<a class='cmotool-checkout' rel='#cmotool-new-checkout-filename'>Check out</a>";
	table += "	</div>"; // cmotool-new-checkout
	table += "</div>";
	return table;
}

function normalizeFilename(filename) {
	return filename.replace('/home/webuser/site/','');
}

function syncTicket(syncData, callback) {
	// Need to parameterize this HOST ADDRESS
	var url = 'http://10.12.1.191:8080/api/changerequests/dup?XDEBUG_SESSION_START=netbeans-xdebug';
	request.Request({
		url: url,
		content:{redmine_url:syncData.url},
		onComplete: function (response) {
			callback(response.json);
		}
	}).post();
}

function checkinFiles(checkinData, callback) {
	console.log('Ticket:' + checkinData.ticket);
	console.log('File:' + checkinData.files[0]);
	// Make sure this is made via POST method with 1 param paths: list of files
	var url = 'http://' + serverHost + ':' + serverPort + '/api/changerequests/' + checkinData.ticket + '/checkin?XDEBUG_SESSION_START=netbeans-xdebug';
	request.Request({
		  url: url,
		  content:{
			  paths: checkinData.files,
		  },
		  onComplete: function (response) {
			  callback(response.json);
		  }
	}).post();
	
}

function checkoutFiles(checkoutData, callback) {
	console.log('Ticket:' + checkoutData.ticket);	
	console.log('Files:' + checkoutData.files.join());
	// Make sure this is made via POST method with 1 param paths: list of files	
	var url = 'http://' + serverHost + ':' + serverPort + '/api/changerequests/' + checkoutData.ticket + '/checkout?XDEBUG_SESSION_START=netbeans-xdebug';
	request.Request({
		  url: url,
		  content: {
			  paths: checkoutData.files
		  },
		  onComplete: function (response) {
			  callback(response.json);
		  }
	}).post();
}